#ifndef ARCH_PAGE_H_
#define ARCH_PAGE_H_

/*
	Copyright (C) 2014 Salil Bhagurkar

	This file is part of illusion

	illusion is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	illusion is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with illusion.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <kernel/types.h>

#define PAGE_SIZE 4096

#define PDE_PRESENT (1 << 0)
#define PDE_WRITE (1 << 1)
#define PDE_USER (1 << 2)
#define PDE_WRITE_THROUGH (1 << 3)
#define PDE_CACHE_DISABLE (1 << 4)
#define PDE_ACCESSED (1 << 5)
#define PDE_PS (1 << 7)



#define PTE_PRESENT (1 << 0)
#define PTE_WRITE (1 << 1)
#define PTE_USER (1 << 2)
#define PTE_WRITE_THROUGH (1 << 3)
#define PTE_CACHE_DISABLE (1 << 4)
#define PTE_ACCESSED (1 << 5)
#define PTE_DIRTY (1 << 6)
#define PTE_PAT (1 << 7)
#define PTE_GLOBAL (1 << 8)


/*
 * Page fault code bits
 */
#define PF_PRESENT (1 << 0)
//0: Due to non-present page
//1: Due to page-level protection violation

#define PF_WR (1 << 1)
//0: Read on page
//1: Write to page

#define PF_US (1 << 2)
//0: Supervisor mode
//1: User mode

#define PF_RSVD (1 << 3)
//0: Not caused due to reserved bit
//1: Caused when reserved bit somewhere in page structures is set to one

#define PF_ID (1 << 4)
//0: Not caused by instruction fetch
//1: Caused by instruction fetch

/*
 * The x86 page system, holding all information required
 * for a particular page mapping
 */
struct page_sys {
	unsigned long *pg_dir;
	//Meta-page access locations
	unsigned long *mav, *mava;
	//Index inside mav which is used to change which page is accessed by using 'mav'
	int mav_index;
};


void implement_page_sys(struct page_sys *page_sys);
void prepare_implement_page_sys(struct page_sys *page_sys);
void enable_page_translation();
void disable_page_translation();
bool is_page_translating();
void map_address(struct page_sys *page_sys, void *phys, void *vaddr,
	unsigned long pde_flags, unsigned long pte_flags, unsigned long trans);
void unmap_address(struct page_sys *page_sys, void **was_phys, void *vaddr);
void get_phys_address(struct page_sys *page_sys, void **phys, unsigned long *flags, void *vaddr);
void init_page_sys(struct page_sys *page_sys, void *kz_start, void *kz_end);
struct page_sys *create_page_sys(struct page_sys *dest, void *kern_area_start, void *kern_area_end);
void destroy_page_sys(struct page_sys *page_sys, void *kern_area_start, void *kern_area_end);

void debug_page_map(void *base);
void debug_page_map_vaddr(void *base, void *vaddr, unsigned long nr_pages);

#endif /* ARCH_PAGE_H_ */
